package cn.xlbweb.cli.service.impl;

import cn.xlbweb.cli.config.CliProperties;
import cn.xlbweb.cli.mapper.RoleMapper;
import cn.xlbweb.cli.mapper.UserMapper;
import cn.xlbweb.cli.mapper.UserRoleMapper;
import cn.xlbweb.cli.model.*;
import cn.xlbweb.cli.common.ServerResponse;
import cn.xlbweb.cli.common.TableResponse;
import cn.xlbweb.cli.pojo.dto.UserInsertDTO;
import cn.xlbweb.cli.pojo.dto.UserUpdateDTO;
import cn.xlbweb.cli.pojo.dto.UsersListDTO;
import cn.xlbweb.cli.service.IUserService;
import cn.xlbweb.cli.util.CliUtils;
import cn.xlbweb.cli.pojo.vo.UserVO;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.crypto.hash.SimpleHash;
import org.apache.shiro.util.ByteSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;

/**
 * @author: bobi
 * @date: 2019-09-15 14:15
 * @description:
 */
@Service
@Slf4j
public class UserServiceImpl implements IUserService {

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private UserRoleMapper userRoleMapper;

    @Autowired
    private RoleMapper roleMapper;

    @Autowired
    private CliProperties cliProperties;

    @Override
    public User getUserByUsername(String username) {
        UserExample userExample = new UserExample();
        userExample.createCriteria().andUsernameEqualTo(username);
        List<User> userList = userMapper.selectByExample(userExample);
        return !userList.isEmpty() ? userList.get(0) : null;
    }

    @Override
    public TableResponse listUsers(UsersListDTO usersListDTO, int pageNum, int pageSize) {
        log.info("listUsers() start...");
        // 构建查询条件
        UserExample userExample = new UserExample();
        if (StringUtils.isNotBlank(usersListDTO.getUsername())) {
            userExample.createCriteria().andUsernameLike("%" + usersListDTO.getUsername() + "%");
        }
        if (StringUtils.isNotBlank(usersListDTO.getEmail())) {
            userExample.createCriteria().andEmailLike("%" + usersListDTO.getEmail() + "%");
        }
        // 构建分页
        PageHelper.startPage(pageNum, pageSize);
        List<User> userList = userMapper.selectByExample(userExample);
        PageInfo<User> userPageInfo = new PageInfo<>(userList);
        // 构建Vo
        List<UserVO> userVOList = new ArrayList<>();
        for (User user : userList) {
            UserVO userVo = new UserVO();
            CliUtils.copyProperties(user, userVo);
            // 查询该用户的所有角色
            UserRoleExample userRoleExample = new UserRoleExample();
            userRoleExample.createCriteria().andUserIdEqualTo(user.getId());
            List<UserRole> userRoleList = userRoleMapper.selectByExample(userRoleExample);
            List<String> roles = new ArrayList<>();
            for (UserRole userRole : userRoleList) {
                Role role = roleMapper.selectByPrimaryKey(userRole.getRoleId());
                roles.add(role.getName());
            }
            userVo.setRoles(roles);
            userVOList.add(userVo);
        }
        log.info("listUsers() end...");
        return TableResponse.success(userPageInfo.getTotal(), userVOList);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public ServerResponse insertUser(UserInsertDTO userInsertDTO) {
        // 判断用户名是否已经存在
        if (StringUtils.isNotBlank(userInsertDTO.getUsername())) {
            return ServerResponse.error("用户名已存在");
        }
        // 加密密码
        String encryptionPassword = new SimpleHash(cliProperties.getAlgorithmName(), userInsertDTO.getPassword(), ByteSource.Util.bytes(userInsertDTO.getUsername()), cliProperties.getHashIterations()).toHex();
        userInsertDTO.setPassword(encryptionPassword);
        // 插入用户
        User user = new User();
        CliUtils.copyProperties(userInsertDTO, user);
        int count = userMapper.insertSelective(user);
        // 插入角色
        insertUserRole(user, userInsertDTO.getRoleIds());
        if (count > 0) {
            return ServerResponse.success("添加成功");
        }
        return ServerResponse.error("插入失败");
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public ServerResponse updateUser(UserUpdateDTO userUpdateDTO) {
        // 判断用户名是否已经存在
        User dbUser = userMapper.selectByPrimaryKey(userUpdateDTO.getId());
        if (!StringUtils.equals(userUpdateDTO.getUsername(), dbUser.getUsername()) && StringUtils.isNotBlank(userUpdateDTO.getUsername())) {
            return ServerResponse.error("用户名已存在");
        }
        // 删除旧角色
        deleteUserRole(String.valueOf(userUpdateDTO.getId()));
        // 更新用户
        CliUtils.copyProperties(userUpdateDTO, dbUser);
        int count = userMapper.updateByPrimaryKeySelective(dbUser);
        // 插入新角色
        insertUserRole(dbUser, userUpdateDTO.getRoleIds());
        if (count > 0) {
            return ServerResponse.success("更新成功");
        }
        return ServerResponse.error("更新失败");
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public ServerResponse deleteUser(String ids) {
        // 删除该用户所拥有的全部角色
        deleteUserRole(ids);
        // 构建删除条件
        UserExample userExample = new UserExample();
        userExample.createCriteria().andIdIn(CliUtils.getIdList(ids));
        // 删除用户
        int count = userMapper.deleteByExample(userExample);
        if (count > 0) {
            return ServerResponse.success("删除成功");
        }
        return ServerResponse.error("删除失败");
    }

    private void insertUserRole(User user, String roleIds) {
        for (Integer roleId : CliUtils.getIdList(roleIds)) {
            UserRole userRole = new UserRole();
            userRole.setUserId(user.getId());
            userRole.setRoleId(roleId);
            Role role = roleMapper.selectByPrimaryKey(roleId);
            userRole.setRemarks(user.getUsername() + "-" + role.getName());
            userRoleMapper.insertSelective(userRole);
        }
    }

    private void deleteUserRole(String userIds) {
        List<Integer> idList = CliUtils.getIdList(userIds);
        UserRoleExample userRoleExample = new UserRoleExample();
        userRoleExample.createCriteria().andUserIdIn(idList);
        int count = userRoleMapper.deleteByExample(userRoleExample);
        if (count > 0) {
            log.info("成功删除{}条用户的角色信息", count);
        }
    }
}
